#include "camera.h"
#include <cmath>
#include <GL/glu.h>

camera::camera(const Vector3D & position)
{
    _position = position;
    _phi = 0;
    _theta = 0;
    VectorsFromAngles();

    _speed = 0.11;
    _sensivity = 0.2;
    _verticalMotionActive = false;
   
    _keystates[EZ] = false;
    _keystates[ES] = false;
    _keystates[ED] = false;
    _keystates[EQ] = false;

    _keystates[Eplus] = false;
    _keystates[Emoins] = false;

    _keystates[EW] = false;

    _relX = 0;
    _relY = 0;
}

void camera::OnMouseMotion()
{
  _theta -= _relX*_sensivity;
  _phi -= _relY*_sensivity;
  VectorsFromAngles();
  _relX = 0;
  _relY = 0;
}

void camera::OnMouseButton()
{
    if (_keystates[Eplus]) 
    {
        _verticalMotionActive = true;
        _timeBeforeStoppingVerticalMotion = 250;
        _verticalMotionDirection = 1;
	_keystates[Eplus]=false;

    }
    else if (_keystates[Emoins])
    {
        _verticalMotionActive = true;
        _timeBeforeStoppingVerticalMotion = 250;
        _verticalMotionDirection = -1;
	_keystates[Emoins]=false;
    }
}

void camera::animate(long timestep)
{
  OnMouseMotion();
  OnMouseButton();

    double realspeed = (_keystates[EW])?10*_speed:_speed;

    if (_keystates[EZ]){
      _position += _forward * (realspeed * timestep);
      _keystates[EZ]=false;
    }

    if (_keystates[ES]){
      _position -= _forward * (realspeed * timestep);
      _keystates[ES]=false;
    }

    if (_keystates[EQ]){
      _position += _left * (realspeed * timestep);
      _keystates[EQ]=false;
    }

    if (_keystates[ED]){
      _position -= _left * (realspeed * timestep);
      _keystates[ED]=false;
    }

    if (_verticalMotionActive)
    {
        if (timestep > _timeBeforeStoppingVerticalMotion)
            _verticalMotionActive = false;
        else
            _timeBeforeStoppingVerticalMotion -= timestep;
        _position += Vector3D(0,0,_verticalMotionDirection*realspeed*timestep);
    }
    _target = _position + _forward;

}

void camera::setSpeed(double speed)
{
    _speed = speed;
}

void camera::setSensivity(double sensivity)
{
    _sensivity = sensivity;
}

void camera::setPosition(const Vector3D & position)
{
    _position = position;
    _target = _position + _forward;
}

Vector3D camera::getPosition()const
{
 return _position;
}
Vector3D camera::getTarget()const
{
  return _target;
}

Vector3D camera::getForward()const
{
  return _forward;
}



void camera::VectorsFromAngles()
{
    static const Vector3D up(0,0,1);
    if (_phi > 89)
        _phi = 89;
    else if (_phi < -89)
        _phi = -89;
    double r_temp = cos(_phi*M_PI/180);
    _forward.Z = sin(_phi*M_PI/180);
    _forward.X = r_temp*cos(_theta*M_PI/180);
    _forward.Y = r_temp*sin(_theta*M_PI/180);

    _left = up.crossProduct(_forward);
    _left.normalize();

    _target = _position + _forward;
}

void camera::look()
{

  gluLookAt(_position.X,_position.Y,_position.Z,
	    _target.X,_target.Y,_target.Z,
	    0,0,1);
}

camera::~camera()
{
}
